package dao

import (
	"fmt"
	"sort"
	"strings"
	"yundian/internel/app/helper"
	"yundian/internel/app/models/placemodel"
	"yundian/internel/app/models/users"
	"yundian/internel/pkg/dingo"
	"yundian/internel/pkg/dingo/global"
)

// CreateWifiUser wifi用户注册
func (d *UserDao) CreateWifiUser(param *users.WifiUserDb) *dingo.ErrorWrap {
	if param.ID > 0 {
		db := global.Orm.Where("id=?", param.ID).Updates(&param)
		return dingo.ErrorIf(db.Error, param)
	}
	db := global.Orm.Create(&param)
	return dingo.ErrorIf(db.Error, param)
}

// CreateInviteRecord 邀请码注册记录
func (d *UserDao) CreateInviteRecord(param *users.InviteRecordDb) *dingo.ErrorWrap {
	db := global.Orm.Create(&param)
	return dingo.ErrorIf(db.Error, param)
}

// GetInviteCodeById 查询用户邀请码
func (d *UserDao) GetInviteCodeById(id int) *dingo.ErrorWrap {
	dbInfo := &users.InviteConfigModel{}
	db := global.Orm.Table("users_invite_config uic").Where("id=?", id)
	db.Find(&dbInfo)
	return dingo.ErrorIf(db.Error, dbInfo)
}

// CreateInviteCode 创建用户邀请码
func (d *UserDao) CreateInviteCode(param *users.InviteConfigDb) *dingo.ErrorWrap {
	db := global.Orm.Create(&param)
	return dingo.ErrorIf(db.Error, param)
}

// GetUserInfoFromId 获取用户信息By id
func (d *UserDao) GetUserInfoFromId(id int) *dingo.ErrorWrap {
	m := &users.UserInfoWithLogin{}
	db := global.Orm.Table("users u").
		Select("u.*,r.name as role_name").
		Joins("left join roles r on u.role_id = r.id").
		Where("u.id = ?", id).Find(m)
	return dingo.ErrorIf(db.Error, m)
}

// GetUserInfoFromPhone 获取用户信息By phone
func (d *UserDao) GetUserInfoFromPhone(phone string) *dingo.ErrorWrap {
	m := users.New()
	db := global.Orm.Debug().Table("users").Where("phone = ?", phone).Find(m)
	return dingo.ErrorIf(db.Error, m)
}

// GetUserInfoFromPhoneInOpenId 获取用户信息By phone
func (d *UserDao) GetUserInfoFromPhoneInOpenId(phone string) *dingo.ErrorWrap {
	m := users.New()
	db := global.Orm.Debug().Table("users u").Select("u.*,IFNULL(wur.openid, '')openid")
	db.Joins("LEFT JOIN wechat_user_relevancy wur on u.id = wur.user_id")
	db.Where("phone = ?", phone)
	db.Find(m)
	return dingo.ErrorIf(db.Error, m)
}

// GetUserInfoFromUnionIdInOpenId 获取用户信息By phone
func (d *UserDao) GetUserInfoFromUnionIdInOpenId(unionId string) *dingo.ErrorWrap {
	m := users.New()
	db := global.Orm.Debug().Table("users u").Select("u.*,IFNULL(wur.openid, '')openid")
	db.Joins("LEFT JOIN wechat_user_relevancy wur on u.id = wur.user_id")
	db.Where("u.unionid = ?", unionId)
	db.Find(m)
	return dingo.ErrorIf(db.Error, m)
}

// CheckUserInfoByPhone 验证相同手机号，排除自己
func (d *UserDao) CheckUserInfoByPhone(phone string, userId int) *dingo.ErrorWrap {
	m := users.New()
	db := global.Orm.Debug().Table("users").Where("phone = ? and id <> ?", phone, userId).Find(m)
	return dingo.ErrorIf(db.Error, m)
}

// GetUserInfoByParentId 获取用户信息By parent_id
func (d *UserDao) GetUserInfoByParentId(pid int) *dingo.ErrorWrap {
	m := users.New()
	sql := "select * from users where parent_id = ?"
	db := global.Orm.Debug().Raw(sql, pid).Find(&m)
	return dingo.ErrorIf(db.Error, m)
}

func (d *UserDao) CountUserByParentId(pid int) *dingo.ErrorWrap {
	var c int64
	sql := "select count(1) from users where parent_id = ?"
	db := global.Orm.Debug().Raw(sql, pid).Find(&c)
	return dingo.ErrorIf(db.Error, c)
}

func (d *UserDao) CountPlaceByUserId(uid int) *dingo.ErrorWrap {
	var c int64
	sql := "select count(1) from places where user_id = ?"
	db := global.Orm.Debug().Raw(sql, uid).Find(&c)
	return dingo.ErrorIf(db.Error, c)
}

// GetUserInfoById 获取用户信息By id
func (d *UserDao) GetUserInfoById(id int) *dingo.ErrorWrap {
	m := users.New()
	if id == 0 {
		return dingo.ErrorIf(nil, m)
	}
	sql := "select * from users where id = ? limit 1"
	db := global.Orm.Raw(sql, id).Find(&m)
	return dingo.ErrorIf(db.Error, m)
}

func (d *UserDao) GetUserNameById(id int) *dingo.ErrorWrap {
	m := users.New()
	if id == 0 {
		return dingo.ErrorIf(nil, m)
	}
	sql := "select name,user_name from users where id = ? limit 1"
	db := global.Orm.Raw(sql, id).Find(&m)
	return dingo.ErrorIf(db.Error, m)
}

// GetUserInfoById 获取用户信息By id
func (d *UserDao) GetUserBranchById(branchName string) *dingo.ErrorWrap {
	var m []users.AgentInfo
	db := global.Orm.Table("users").
		Select("id ,user_name,name,phone")

	if branchName != "" {
		db.Where("user_name like ?", fmt.Sprint("%", branchName, "%"))
	}

	db.Where("is_place = 3").Limit(20).Find(&m)
	fmt.Println(db.Error)
	return dingo.ErrorIf(db.Error, m)
}

func (d *UserDao) GetUserAgentById(agentName string, isAdmin uint8) *dingo.ErrorWrap {
	var m []users.AgentInfo
	db := global.Orm.Table("users").
		Select("id ,user_name,name,phone")

	if agentName != "" {
		db.Where("user_name like ? or name like ? ", fmt.Sprint("%", agentName, "%"), fmt.Sprint("%", agentName, "%"))
	}

	if isAdmin != helper.TypeNumIsAdminOperator && isAdmin != helper.TypeNumIsAdminAdministrator && isAdmin != helper.TypeNumIsAdminStaff {
		db.Where("is_admin = ?", isAdmin)
	}

	db.Limit(20).Find(&m)
	fmt.Println(db.Error)
	return dingo.ErrorIf(db.Error, m)
}

// GetUserInfoByUserId 获取商户详情By user_id
func (d *UserDao) GetUserInfoByUserId(userId int) *dingo.ErrorWrap {
	m := users.UserInfoPlaceId{}
	sql := "select u.*,p.id as place_id,place_name from users u inner join places p on u.id = p.user_id where u.id = ?"
	db := global.Orm.Raw(sql, userId).Find(&m)
	return dingo.ErrorIf(db.Error, m)
}

// GetUserInfoByPlaceId 获取商户详情By place_id
func (d *UserDao) GetUserInfoByPlaceId(placeId int) *dingo.ErrorWrap {
	m := users.New()
	sql := "select u.* from users u inner join places p on u.id = p.user_id where p.id = ?"
	db := global.Orm.Raw(sql, placeId).Find(&m)
	return dingo.ErrorIf(db.Error, m)
}

func (d *UserDao) GetUserProfileByPlaceId(placeId int) *dingo.ErrorWrap {
	m := &users.UserProfileWithPlace{}
	sql := "select u.*,p.branch_user_id from users u inner join places p on u.id = p.user_id where p.id = ?"
	db := global.Orm.Raw(sql, placeId).Find(&m)
	return dingo.ErrorIf(db.Error, m)
}

// 获取网点详情
func (d *UserDao) GetUserKaInfoByPlaceId(placeId int) *dingo.ErrorWrap {
	m := users.New()
	sql := "select u.*,p.ka_user_id from users u inner join places p on u.id = p.user_id where p.id = ?"
	db := global.Orm.Raw(sql, placeId).Find(&m)
	return dingo.ErrorIf(db.Error, m)
}

// 获取分公司用户
func (d *UserDao) GetUserInfoByKaUserIds(branchUserId int) *dingo.ErrorWrap {
	m := users.New()
	sql := fmt.Sprintf("select * from users u where u.id=?")
	db := global.Orm.Raw(sql, branchUserId).Find(&m)
	return dingo.ErrorIf(db.Error, m)
}

// 根据网点ID查询分公司用户
func (d *UserDao) GetBranchUserInfoByPlaceId(placeId int) *dingo.ErrorWrap {
	m := users.New()
	sql := "select u.* from users u inner join places p on u.id = p.branch_user_id where p.id=?"
	db := global.Orm.Raw(sql, placeId).Find(&m)
	return dingo.ErrorIf(db.Error, m)
}

// 递归查询所有代理商/KA
func (d *UserDao) QueryParentList(parentID, kaUserId int) *dingo.ErrorWrap {
	var m = users.UserModel{ParentID: parentID}
	var list []*users.UserModel
	list, err := d.QueryParentListAll(&m, list, 0)

	if kaUserId > 0 {
		list = append(list, d.GetUserInfoById(kaUserId).Unwrap().(*users.UserModel))
	}

	//var newList []*users.UserModel
	//for _, item := range list {
	//	if item.IsDivinds != 2 {
	//		newList = append(newList, item)
	//	}
	//}

	//userList := newList

	userList := list
	sort.Slice(userList, func(i, j int) bool {
		if userList[i].ProfitProportion != userList[j].ProfitProportion {
			return userList[i].ProfitProportion < userList[j].ProfitProportion
		}
		if userList[i].IsAdmin != userList[j].IsAdmin {
			return userList[i].IsAdmin > userList[j].IsAdmin
		}

		IsPlaces := "1230"
		iIndex := strings.Index(IsPlaces, fmt.Sprintf("%d", userList[i].IsPlace))
		jIndex := strings.Index(IsPlaces, fmt.Sprintf("%d", userList[j].IsPlace))
		return iIndex < jIndex
		//return userList[i].IsPlace < userList[j].IsPlace
	})
	return dingo.ErrorIf(err, userList)
}

// 递归查询所有代理商/KA
func (d *UserDao) QueryParentListAll(userInfo *users.UserModel, userList []*users.UserModel, num int) ([]*users.UserModel, error) {
	num++
	if userInfo.ParentID <= 0 || num > 100 {
		return userList, nil
	}

	resultUserInfo := d.GetUserInfoById(userInfo.ParentID)
	if resultUserInfo.Err != nil {
		return userList, resultUserInfo.Err
	}

	targetUserInfo := resultUserInfo.Unwrap().(*users.UserModel)
	userList = append(userList, targetUserInfo)

	return d.QueryParentListAll(targetUserInfo, userList, num)
}

// 根据代理商查询所有下级商户id
func (d *UserDao) QueryChildUserIds(userId int) *dingo.ErrorWrap {
	pidArr := []int{userId}
	userIdArr := make([]int, 0)
	isRecursive := true

	queryNum := 0

	// 递归 无限查询下级
	for isRecursive {
		tempUserIdArr := NewUserDao().GetUserIdByPid(pidArr).Unwrap().([]int)

		if len(tempUserIdArr) == 0 || queryNum > 100 {
			isRecursive = false
		} else {
			queryNum++
			userIdArr = append(userIdArr, tempUserIdArr...)
			pidArr = tempUserIdArr
		}
	}
	userIdArr = append(userIdArr, userId)

	return dingo.ErrorIf(nil, userIdArr)
}

//根据代理商查询所有网点
func (d *UserDao) QueryChildPlacesIds(userId int) *dingo.ErrorWrap {
	pidArr := []int{userId}
	userIdArr := make([]int, 0)
	isRecursive := true

	queryNum := 0

	// 递归 无限查询下级
	for isRecursive {
		tempUserIdArr := NewUserDao().GetUserIdByPid(pidArr).Unwrap().([]int)

		if len(tempUserIdArr) == 0 || queryNum > 100 {
			isRecursive = false
		} else {
			queryNum++
			userIdArr = append(userIdArr, tempUserIdArr...)
			pidArr = tempUserIdArr
		}
	}
	userIdArr = append(userIdArr, userId)

	return dingo.ErrorIf(nil, userIdArr)
}

// GetUserInfoByopenid 获取用户信息By openid
func (d *UserDao) GetUserInfoByopenid(openid string) *dingo.ErrorWrap {
	m := users.New()
	sql := `select * from users where openid = ?`
	db := global.Orm.Raw(sql, openid).Find(&m)
	return dingo.ErrorIf(db.Error, m)
}

func (d *UserDao) GetUserInfoByZfbOpenid(openid string) *dingo.ErrorWrap {
	m := users.New()
	sql := `select * from users where zfb_openid = ?`
	db := global.Orm.Raw(sql, openid).Find(&m)
	return dingo.ErrorIf(db.Error, m)
}

// GetUserInfoByUnionId 获取用户信息By unionid
func (d *UserDao) GetUserInfoByUnionId(unionid string) *dingo.ErrorWrap {
	m := users.New()
	sql := `select * from users where unionid = ?`
	db := global.Orm.Raw(sql, unionid).Find(&m)
	return dingo.ErrorIf(db.Error, m)
}

// GetUserInfoByPhone 获取用户信息By phone
func (d *UserDao) GetUserInfoByPhone(phone string) *dingo.ErrorWrap {
	m := users.New()
	sql := `select * from users where phone = ?`
	db := global.Orm.Raw(sql, phone).Find(&m)
	return dingo.ErrorIf(db.Error, m)
}

// GetFromUserName 获取用户信息By user_name
func (d *UserDao) GetUserInfoFromUserName(username string) *dingo.ErrorWrap {
	m := users.New()
	db := global.Orm.Table("users").Where("username = ?", username).Find(&m)
	return dingo.ErrorIf(db.Error, m)
}

//获取代理商上级的分成比例
func (d *UserDao) GetParentProfitProportion(id int) *dingo.ErrorWrap {
	m := users.New()
	sqlStr := "SELECT" +
		" (SELECT profit_proportion from users where id = u.parent_id ) AS profit_proportion" +
		" FROM" +
		" users u" +
		" WHERE" +
		" u.id = ? "
	//db := global.Orm.Table("users").Select("(SELECT profit_proportion from users where id = parent_id )").Where("id = ?", id).Find(&param)
	db := global.Orm.Raw(sqlStr, id).Find(&m)
	return dingo.ErrorIf(db.Error, m)
}

func (d *UserDao) DeleteUserById(userId int) *dingo.ErrorWrap {
	db := global.Orm.Exec("delete from users where id = ?", userId)
	return dingo.ErrorIf(db.Error, true)
}

func (d *UserDao) GetUserBranchList(userId int) *dingo.ErrorWrap {
	var lst []placemodel.PlaceModel
	db := global.Orm.Table("places").Where("ka_user_id = ?", userId).Find(&lst)
	return dingo.ErrorIf(db.Error, lst)
}

func (d *UserDao) PlacesBatchDelete(queryStr string, queryVal *[]interface{}) error {
	p := placemodel.NewPlaceModel()
	db := global.Orm.Table("places").Where(queryStr, *queryVal...).Delete(&p)
	return db.Error
}

func (d *UserDao) GetAgentInfo(id int) *dingo.ErrorWrap {
	var lst []users.UserModel
	db := global.Orm.Table("users").Where("parent_id = ?", id).Find(&lst)
	return dingo.ErrorIf(db.Error, lst)
}

func (d *UserDao) GetPlacesUserInfo(id int) *dingo.ErrorWrap {
	var lst []users.UserModel
	db := global.Orm.Table("users").Where("parent_id = ?", id).Find(&lst)
	return dingo.ErrorIf(db.Error, lst)
}

func (d *UserDao) UpdateUserQRCode(id int, updateVal *users.UserModel) *dingo.ErrorWrap {
	db := global.Orm.Table("users").Select("wx_income_qrcode").Where("id = ?", id).Model(&updateVal).Updates(&updateVal)
	return dingo.ErrorIf(db.Error, true)
}

func (d *UserDao) GetUserIsDraw(userId int) *dingo.ErrorWrap {
	var idDraw int
	db := global.Orm.Table("users").Select("is_draw").Where("id = ?", userId).Find(&idDraw)
	return dingo.ErrorIf(db.Error, idDraw)
}

func (d *UserDao) GetUserIsDrawByUserIds(userIds []int) *dingo.ErrorWrap {
	var agentUserIsDraw []users.AgentUserIsDraw
	db := global.Orm.Table("users").Select("is_draw,id").Where("id in (?)", userIds).Find(&agentUserIsDraw)
	return dingo.ErrorIf(db.Error, agentUserIsDraw)
}

func (d *UserDao) GetUserIds() *dingo.ErrorWrap {
	var ids []int
	sql := "SELECT id FROM users WHERE FIND_IN_SET('zmadmin', platform) or FIND_IN_SET('hotel', platform)"
	db := global.Orm.Raw(sql).Find(&ids)
	return dingo.ErrorIf(db.Error, ids)
	//db := global.Orm.Table("users").Select("id").Find(&ids)
	//return dingo.ErrorIf(db.Error, ids)
}

func (d *UserDao) GetBranchUserIds() *dingo.ErrorWrap {
	var branchIds []int
	db := global.Orm.Table("users").Select("id").Where("is_admin = ? ", helper.TypeNumIsAdminBranch).Find(&branchIds)
	return dingo.ErrorIf(db.Error, branchIds)
}

// 修改所属平台
func (d *UserDao) UpdateUserPlatform(platform string, id int) *dingo.ErrorWrap {
	m := &users.UserModel{}
	m.Platform = platform
	db := global.Orm.Table("users").
		Select("platform").
		Where("id = ?", id).
		Model(&m).Updates(m)
	if db.Error != nil {
		return dingo.ErrorIf(db.Error, false)
	}
	return dingo.ErrorIf(db.Error, true)
}
